iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
自我挑戰組

全端網頁-入職三十天學習筆記系列 第 23

【全端網頁開發】Day23-Echart-flask實做資料可視化

  • 分享至 

  • xImage
  •  

前言

也是記錄一些針對部分功能的小專案,
這篇會是資料庫查詢圖表呈現
那前端要做到圖表呈現也有滿多種,
今天主要使用的是Echart來幫助我們做到資料可視化,
那這篇還會包含記錄到後端連線資料庫的部分。

Echart-資料庫查詢圖表呈現

1.將資料表資訊分開存放於models.py ,使用時才進行匯入

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

# PostgreSQL 連接信息
db_host = '***'
db_port = '***'
db_user = '***'
db_password = '***'
db_name = '***'

class ByPcsSummary(Base):
    __tablename__ = "by_pcs_summary"
    id= Column(Integer, primary_key=True)
    Plant= Column(String)
    Line= Column(String)
    Date= Column(String)
    Section= Column(Integer)
    AOI_Input= Column(Integer)
    AI_Input= Column(Integer)
    OKOK= Column(Integer)
    NGNG= Column(Integer)
    NTF= Column(Integer)

class ByPointSummary(Base):
    __tablename__ = "by_point_summary"
    id= Column(Integer, primary_key=True)
    PositionID=Column(String)
    Product= Column(String)
    Date= Column(String)
    Line= Column(String)
    AIModel= Column(Integer)
    OKOK= Column(Integer)
    NGNG= Column(Integer)
    Total= Column(Integer)
    NTF= Column(Integer)

2.後端部分使用sqlalchemy連線資料庫進行查詢

# 創建 SQLAlchemy 引擎
db_url = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
engine = create_engine(db_url)

# 定義 ORM 映射
Base = declarative_base()

# 創建一個 Session 類型以進行數據庫交互
Session = sessionmaker(bind=engine)

3.查詢後將資料轉換為json格式回傳網頁

@chart.route('/pcs_query', methods=['GET','POST'])
def pcs_query_data():
    date = request.form.get('date')
    line = request.form.get('line')


    # 創建一個會話對象
    session = Session()

    # 執行查詢
    query_result = session.query(ByPcsSummary.id,ByPcsSummary.Plant,ByPcsSummary.Line,ByPcsSummary.Date,\
    ByPcsSummary.Section,ByPcsSummary.AOI_Input,ByPcsSummary.AI_Input,ByPcsSummary.OKOK,ByPcsSummary.NGNG,ByPcsSummary.NTF) \
    .filter(ByPcsSummary.Date == date,ByPcsSummary.Line == line)\
    .order_by(ByPcsSummary.id).limit(150).all()

    # 關閉
    session.close()

    # 將查詢結果轉換為 JSON 格式
    result = [
        {
            'Plant': row.Plant,
            'ID': row.id,
            'Section': row.Section,
            'AOI_Input': row.AOI_Input,
            'AI_Input': row.AI_Input,
            'NTF': row.NTF,
            'OKOK': row.OKOK,
            'NGNG': row.NGNG
        } 
        for row in query_result
        ]

    return render_template('chart_pcs.html', result=result,date=date,line=line)

@chart.route('/point_query', methods=['GET','POST'])
def point_query_data():
    date = request.form.get('date')
    line = request.form.get('line')


    # 創建一個會話對象
    session = Session()

    # 執行查詢
    query_result = session.query(ByPointSummary.PositionID,ByPointSummary.Product,ByPointSummary.Line,ByPointSummary.AIModel,\
    ByPointSummary.NTF,ByPointSummary.NGNG,ByPointSummary.OKOK,ByPointSummary.Total) \
    .filter(ByPointSummary.Date == date,ByPointSummary.Line == line)\
    .order_by(ByPointSummary.id).limit(150).all()

    # 關閉
    session.close()

    # 將查詢結果轉換為 JSON 格式
    result = [
        {
            'PositionID': row.PositionID,
            'Product': row.Product,
            'Line': row.Line,
            'AIModel': row.AIModel,
            'NTF': row.NTF,
            'OKOK': row.OKOK,
            'NGNG': row.NGNG,
            'Total': row.Total
        } 
        for row in query_result
        ]

    return render_template('chart_point.html', result=result,date=date,line=line)

4.使用map函數從data數組中提取值存放
5.設定圖表的欄位及各項配置
6.寫進圖表所使用的各項值

Chart_pcs.html

<div class="container mt-3">
            <div id="chart" style="height: 350px"></div>

        </div>


        <script type="text/javascript">
            var data = {{ result | safe}};

            var aiInputValues = data.map(function (item) {
                return item.AI_Input;
            });

            var aoiInputValues = data.map(function (item) {
                return item.AOI_Input;
            });

            var ngngValues = data.map(function (item) {
                return item.NGNG;
            });

            var okokValues = data.map(function (item) {
                return item.OKOK;
            });

            var plantValues = data.map(function (item) {
                return item.Plant;
            });

            var sectionValues = data.map(function (item) {
                return item.Section;
            });

            var ID = data.map(function (item) {
                return item.ID;
            });

            // 創建 ECharts 選項
            var option = {
                tooltip: {
                    trigger: 'axis',
                    formatter: function (params) {
                        var dataIndex = params[0].dataIndex;
                        var tooltipText = 'Section: ' + sectionValues[dataIndex] + '<br>';
                        tooltipText += 'ID: ' + ID[dataIndex] + '<br>';
                        tooltipText += 'Plant: ' + plantValues[dataIndex] + '<br>';

                        params.forEach(function (param) {
                            tooltipText += param.seriesName + ': ' + param.value + '<br>';
                        });
                        return tooltipText;
                    }
                },
                legend: {
                    data: ['AI_Input', 'AOI_Input', 'NGNG', 'OKOK']
                },
                xAxis: {
                    type: 'category',
                    data: sectionValues
                },
                yAxis: [
                    {
                        type: 'value',
                        name: 'AI_Input & AOI_Input',
                        position: 'left',
                        axisLabel: {
                            formatter: '{value}'
                        }
                    },
                    {
                        type: 'value',
                        name: 'NGNG & OKOK',
                        position: 'right',
                        axisLabel: {
                            formatter: '{value}'
                        }
                    }
                ],
                series: [
                    {
                        name: 'AI_Input',
                        type: 'bar',
                        data: aiInputValues
                    },
                    {
                        name: 'AOI_Input',
                        type: 'bar',
                        data: aoiInputValues
                    },
                    {
                        name: 'NGNG',
                        type: 'line',
                        yAxisIndex: 1, // 使用右側的 Y 軸
                        data: ngngValues
                    },
                    {
                        name: 'OKOK',
                        type: 'line',
                        yAxisIndex: 1, // 使用右側的 Y 軸
                        data: okokValues
                    }
                ]
            };

            // 初始化 ECharts 圖表
            var dom = document.getElementById('chart');
            var myChart = echarts.init(dom);
            if (option && typeof option === 'object') {
                myChart.setOption(option);
            }
        </script>

chart_point.html

<div class="container mt-3">
            <div id="chart" style="height: 350px"></div>

        </div>

        
        <script type="text/javascript">
            var data = {{ result | safe }};

            var AIModelValues = data.map(function (item) {
                return item.AIModel;
            });

            var NTFValues = data.map(function (item) {
                return item.NTF;
            });

            var ngngValues = data.map(function (item) {
                return item.NGNG;
            });

            var okokValues = data.map(function (item) {
                return item.OKOK;
            });

            var ProductValues = data.map(function (item) {
                return item.Product;
            });


            var TotalValues = data.map(function (item) {
                return item.Total;
            });

            var PositionID = data.map(function (item) {
                return item.PositionID;
            });

            // 創建 ECharts 選項
            var option = {
                tooltip: {
                    trigger: 'axis',
                    formatter: function (params) {
                        var dataIndex = params[0].dataIndex;
                        var tooltipText = 'PositionID: ' + PositionID[dataIndex] + '<br>';
                        tooltipText += 'Product: ' + ProductValues[dataIndex] + '<br>';
                        
                        params.forEach(function (param) {
                            tooltipText += param.seriesName + ': ' + param.value + '<br>';
                        });
                        return tooltipText;
                    }
                },
                legend: {
                    data: ['AIModel', 'NTF', 'NGNG', 'OKOK','Total']
                },
                xAxis: {
                    type: 'category',
                    data: PositionID
                },
                yAxis: [
                    {
                        type: 'value',
                        name: 'AIModel & NTF',
                        position: 'left',
                        axisLabel: {
                            formatter: '{value}'
                        }
                    },
                    {
                        type: 'value',
                        name: 'NGNG & OKOK & Total',
                        position: 'right',
                        axisLabel: {
                            formatter: '{value}'
                        }
                    }
                ],
                series: [
                    {
                        name: 'AIModel',
                        type: 'bar',
                        data: AIModelValues
                    },
                    {
                        name: 'NTF',
                        type: 'bar',
                        data: NTFValues
                    },
                    {
                        name: 'NGNG',
                        type: 'line',
                        yAxisIndex: 1, // 使用右側的 Y 軸
                        data: ngngValues
                    },
                    {
                        name: 'OKOK',
                        type: 'line',
                        yAxisIndex: 1, // 使用右側的 Y 軸
                        data: okokValues
                    },
                    {
                        name: 'Total',
                        type: 'line',
                        yAxisIndex: 1, // 使用右側的 Y 軸
                        data: TotalValues
                    }
                ]
            };

            // 初始化 ECharts 圖表
            var dom = document.getElementById('chart');
            var myChart = echarts.init(dom);
            if (option && typeof option === 'object') {
                myChart.setOption(option);
            }
        </script>

結語

本篇主要記錄小功能的部分程式碼重點,
若有用到相同功能可以依照程式碼做參考去撰寫~


上一篇
【全端網頁開發】Day22-JsTree-flask實做前端樹狀結構UI
下一篇
【全端網頁開發】Day24- RESTful API 入門指南
系列文
全端網頁-入職三十天學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言